/*
 * Copyright (c) 2010-2011 Plugger Antonio Begue Ponce. All Rights Reserved.
 *
 * This file is part of Plugger Framework.
 *
 *  Plugger Framework is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License version 3 as published by
 *  the Free Software Foundation.
 *
 *  Plugger Framework is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with Plugger Framework.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.plugger.infrastructure.repositorybase;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import org.plugger.infrastructure.domainbase.IAggregateRoot;
import org.plugger.infrastructure.domainbase.KeyObject;

/**
 * An abstract representation of a repository.<BR/>
 * Only an AggregateRoot can be used to create a repository.<BR/>
 * The repository uses a workspace (unit of work) to retrieve entities from persistence.<BR/>
 * Each entity is responsible to retrieve theirs value objects.<BR/>
 * Every database query should be stored inside the respective repository.
 *
 * @author Antonio Begue
 * @version $Revision: 1.0 $
 *
 * @see     IWorkspace
 * @see     IRepository
 */
public abstract class RepositoryBase<T extends IAggregateRoot> implements IRepository<T> {
    private IWorkspace ws;
    private Class<T> persistentClass;

    /**
     * Construct a RepositoryBase receiving a workspace
     *
     * @param ws The IWorkspace to be used.
     */
    protected RepositoryBase(IWorkspace ws) {
        this.ws = ws;
    }

    /**
     * The workspace is the unit of work for this repository.
     *
     * @return The IWorkspace to be used.
     */
    protected IWorkspace getWorkspace() {
        return this.ws;
    }

    // <editor-fold defaultstate="collapsed" desc="IRepository<T> Members">
    @Override
    public T getById(Object id) {
        Serializable serialId = KeyObject.getInstance().getSerialKey(id);
        return ws.getById(this.getPersistentClass(), serialId);
    }

    @Override
    public List<T> getAll() {
        return ws.getAll(getPersistentClass());
    }

    public void add(T item) {
        ws.makePersistent(item);
    }

    public void remove(T item) {
        ws.delete(item);
    }
    // </editor-fold>

    /**
     * The Class<T> of the persistent entity.
     *
     * @return the persistentClass
     */
    public Class<T> getPersistentClass() {
        if (persistentClass == null) {
            Class<?> cls = getClass();
            Type tt = cls.getGenericSuperclass();
            Type ttt = ((ParameterizedType) tt).getActualTypeArguments()[0];
            this.persistentClass = (Class<T>) ttt;
            //this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        }
        return persistentClass;
    }

    /**
     * The Class<T> of the persistent entity.
     * 
     * @param persistentClass the persistentClass to set
     */
    public void setPersistentClass(Class<T> persistentClass) {
        this.persistentClass = persistentClass;
    }
}
